"""
Celery 任务定义

所有异步任务的实现
"""

import time
import random
from typing import List, Dict, Any
from celery import Task
from celery.exceptions import SoftTimeLimitExceeded
import sys
from pathlib import Path

# 处理导入路径
if __name__ == "__main__" or "." not in __name__:
    sys.path.insert(0, str(Path(__file__).parent.parent.parent))
    from stage2_advanced.chapter04_background_tasks.celery_app import celery_app
    from stage2_advanced.chapter04_background_tasks.config import (
        TaskQueues,
        RetryConfig,
        EMAIL_CONFIG,
    )
else:
    from .celery_app import celery_app
    from .config import TaskQueues, RetryConfig, EMAIL_CONFIG


# ========== 基础示例任务 ==========

@celery_app.task(name="tasks.add")
def add(x: int, y: int) -> int:
    """
    简单的加法任务（用于测试）
    
    Args:
        x: 第一个数
        y: 第二个数
        
    Returns:
        两数之和
    """
    return x + y


@celery_app.task(name="tasks.multiply")
def multiply(x: int, y: int) -> int:
    """
    乘法任务
    
    Args:
        x: 第一个数
        y: 第二个数
        
    Returns:
        两数之积
    """
    time.sleep(2)  # 模拟耗时操作
    return x * y


# ========== 长时间运行的任务 ==========

@celery_app.task(
    name="tasks.long_running_task",
    bind=True,  # 绑定任务实例
    max_retries=3,
    soft_time_limit=300  # 5分钟软超时
)
def long_running_task(self, duration: int = 10) -> Dict[str, Any]:
    """
    长时间运行的任务（支持进度更新）
    
    Args:
        self: 任务实例
        duration: 运行时长（秒）
        
    Returns:
        任务执行结果
    """
    total_steps = duration
    
    for i in range(total_steps):
        # 更新任务状态和进度
        self.update_state(
            state='PROGRESS',
            meta={
                'current': i + 1,
                'total': total_steps,
                'percent': int((i + 1) / total_steps * 100),
                'status': f'Processing step {i + 1}/{total_steps}'
            }
        )
        
        # 模拟工作
        time.sleep(1)
    
    return {
        'status': 'completed',
        'result': f'Processed {total_steps} steps successfully',
        'duration': duration
    }


# ========== 重试任务示例 ==========

@celery_app.task(
    name="tasks.task_with_retry",
    bind=True,
    autoretry_for=(Exception,),  # 自动重试的异常类型
    retry_backoff=True,           # 指数退避
    retry_backoff_max=600,        # 最大退避时间
    retry_jitter=True,            # 添加随机抖动
    max_retries=RetryConfig.max_retries
)
def task_with_retry(self, success_rate: float = 0.3):
    """
    会随机失败的任务（用于演示重试机制）
    
    Args:
        self: 任务实例
        success_rate: 成功率（0.0-1.0）
        
    Returns:
        成功消息
        
    Raises:
        Exception: 模拟失败
    """
    if random.random() > success_rate:
        # 模拟失败
        raise Exception(f"Task failed randomly (attempt {self.request.retries + 1})")
    
    return {
        'status': 'success',
        'message': 'Task completed successfully!',
        'attempts': self.request.retries + 1
    }


# ========== 邮件发送任务 ==========

@celery_app.task(
    name="tasks.send_email",
    queue=TaskQueues.EMAIL,
    max_retries=5,
    retry_backoff=True
)
def send_email(
    to_email: str,
    subject: str,
    body: str,
    html: bool = False
) -> Dict[str, Any]:
    """
    发送邮件任务
    
    Args:
        to_email: 收件人邮箱
        subject: 邮件主题
        body: 邮件正文
        html: 是否为 HTML 格式
        
    Returns:
        发送结果
    """
    # 这里只是示例，实际应该使用 SMTP 库
    print(f"Sending email to {to_email}")
    print(f"Subject: {subject}")
    print(f"Body: {body}")
    
    # 模拟发送延迟
    time.sleep(2)
    
    return {
        'status': 'sent',
        'to': to_email,
        'subject': subject,
        'timestamp': time.time()
    }


@celery_app.task(name="tasks.send_bulk_emails")
def send_bulk_emails(email_list: List[Dict[str, str]]) -> Dict[str, Any]:
    """
    批量发送邮件
    
    Args:
        email_list: 邮件列表，每个元素包含 to, subject, body
        
    Returns:
        发送统计
    """
    results = {
        'total': len(email_list),
        'sent': 0,
        'failed': 0,
        'details': []
    }
    
    for email_data in email_list:
        try:
            result = send_email.apply_async(
                args=[
                    email_data['to'],
                    email_data['subject'],
                    email_data['body']
                ]
            )
            results['sent'] += 1
            results['details'].append({
                'to': email_data['to'],
                'status': 'queued',
                'task_id': result.id
            })
        except Exception as e:
            results['failed'] += 1
            results['details'].append({
                'to': email_data['to'],
                'status': 'failed',
                'error': str(e)
            })
    
    return results


# ========== 文件处理任务 ==========

@celery_app.task(
    name="tasks.process_image",
    queue=TaskQueues.FILE_PROCESSING,
    bind=True
)
def process_image(self, image_path: str, operations: List[str]) -> Dict[str, Any]:
    """
    处理图片任务
    
    Args:
        self: 任务实例
        image_path: 图片路径
        operations: 操作列表（如 ['thumbnail', 'watermark']）
        
    Returns:
        处理结果
    """
    results = {
        'original_path': image_path,
        'operations_completed': [],
        'errors': []
    }
    
    total_ops = len(operations)
    
    for i, operation in enumerate(operations):
        # 更新进度
        self.update_state(
            state='PROGRESS',
            meta={
                'current': i + 1,
                'total': total_ops,
                'operation': operation
            }
        )
        
        try:
            # 模拟处理
            time.sleep(1)
            results['operations_completed'].append(operation)
        except Exception as e:
            results['errors'].append({
                'operation': operation,
                'error': str(e)
            })
    
    return results


@celery_app.task(name="tasks.generate_thumbnail")
def generate_thumbnail(
    image_path: str,
    sizes: List[str] = ["small", "medium", "large"]
) -> Dict[str, Any]:
    """
    生成缩略图任务
    
    Args:
        image_path: 原图路径
        sizes: 要生成的尺寸列表
        
    Returns:
        生成的缩略图路径
    """
    # 这里只是示例，实际应该调用图片处理库
    thumbnails = {}
    
    for size in sizes:
        # 模拟生成缩略图
        time.sleep(0.5)
        thumbnails[size] = f"{image_path}_{size}_thumb.jpg"
    
    return {
        'original': image_path,
        'thumbnails': thumbnails,
        'status': 'completed'
    }


# ========== 报表生成任务 ==========

@celery_app.task(
    name="tasks.generate_report",
    queue=TaskQueues.REPORT,
    bind=True,
    soft_time_limit=600  # 10分钟
)
def generate_report(
    self,
    report_type: str,
    start_date: str,
    end_date: str
) -> Dict[str, Any]:
    """
    生成报表任务
    
    Args:
        self: 任务实例
        report_type: 报表类型
        start_date: 开始日期
        end_date: 结束日期
        
    Returns:
        报表信息
    """
    steps = ['数据收集', '数据处理', '报表生成', '报表保存']
    total_steps = len(steps)
    
    try:
        for i, step in enumerate(steps):
            # 更新进度
            self.update_state(
                state='PROGRESS',
                meta={
                    'current': i + 1,
                    'total': total_steps,
                    'step': step,
                    'percent': int((i + 1) / total_steps * 100)
                }
            )
            
            # 模拟处理
            time.sleep(2)
        
        return {
            'status': 'completed',
            'report_type': report_type,
            'period': f'{start_date} to {end_date}',
            'file_path': f'/reports/{report_type}_{start_date}_{end_date}.pdf'
        }
        
    except SoftTimeLimitExceeded:
        # 处理超时
        return {
            'status': 'timeout',
            'message': 'Report generation exceeded time limit'
        }


# ========== 定时任务示例 ==========

@celery_app.task(name="tasks.test_periodic_task")
def test_periodic_task():
    """
    测试定时任务（每30秒执行一次）
    """
    print(f"Periodic task executed at {time.time()}")
    return {
        'status': 'executed',
        'timestamp': time.time()
    }


@celery_app.task(name="tasks.cleanup_old_files")
def cleanup_old_files() -> Dict[str, Any]:
    """
    清理旧文件（每天执行一次）
    """
    print("Cleaning up old files...")
    
    # 模拟清理过程
    time.sleep(3)
    
    return {
        'status': 'completed',
        'files_deleted': random.randint(0, 100),
        'space_freed': f'{random.randint(100, 1000)} MB'
    }


@celery_app.task(name="tasks.generate_hourly_report")
def generate_hourly_report() -> Dict[str, Any]:
    """
    生成小时报表（每小时执行一次）
    """
    print("Generating hourly report...")
    
    time.sleep(5)
    
    return {
        'status': 'completed',
        'report_type': 'hourly',
        'timestamp': time.time()
    }


# ========== 链式任务示例 ==========

@celery_app.task(name="tasks.step1")
def step1(data: str) -> str:
    """任务链的第一步"""
    time.sleep(1)
    return f"Step1({data})"


@celery_app.task(name="tasks.step2")
def step2(data: str) -> str:
    """任务链的第二步"""
    time.sleep(1)
    return f"Step2({data})"


@celery_app.task(name="tasks.step3")
def step3(data: str) -> str:
    """任务链的第三步"""
    time.sleep(1)
    return f"Step3({data})"


# ========== 组任务示例 ==========

@celery_app.task(name="tasks.process_item")
def process_item(item_id: int) -> Dict[str, Any]:
    """
    处理单个项目（用于组任务）
    
    Args:
        item_id: 项目 ID
        
    Returns:
        处理结果
    """
    time.sleep(random.uniform(0.5, 2.0))
    
    return {
        'item_id': item_id,
        'status': 'processed',
        'timestamp': time.time()
    }


# ========== 错误处理任务 ==========

@celery_app.task(
    name="tasks.task_with_error_handling",
    bind=True
)
def task_with_error_handling(self, data: Any) -> Dict[str, Any]:
    """
    带错误处理的任务示例
    
    Args:
        self: 任务实例
        data: 任务数据
        
    Returns:
        处理结果
    """
    try:
        # 模拟可能失败的操作
        if not data:
            raise ValueError("Data cannot be empty")
        
        # 处理数据
        time.sleep(2)
        result = f"Processed: {data}"
        
        return {
            'status': 'success',
            'result': result
        }
        
    except ValueError as e:
        # 记录错误但不重试
        return {
            'status': 'error',
            'error': str(e),
            'error_type': 'ValueError'
        }
        
    except Exception as e:
        # 其他错误，尝试重试
        raise self.retry(exc=e, countdown=60)  # 60秒后重试

